"""SciPy的linalg模块是SciPy库中的一个子模块，它提供了许多用于线性代数运算的函数和工具，
如矩阵求逆、特征值、行列式、线性方程组求解等。

相比于NumPy的linalg模块，SciPy的linalg模块包含更多的高级功能，
并且在处理一些特定的数值计算问题时，可能会表现出更好的性能。

1.
主要功能
scipy.linalg模块主要功能包括：

类别
主要函数
说明
基础运算
包含inv，slove等20多个函数
求解逆矩阵，线性方程等等
特征值问题
包含eig，eigvals等8个函数
求解各种类型矩阵的特征值
分解运算
包含lu，svd等将近30个函数
矩阵的LU分解，奇异值分解等等
矩阵运算
包含logm，sinm，cosm等10多个函数
计算矩阵的对数，指数，sin，cos等等
矩阵方程求解
包含solve_sylvester，solve_continuous_are等5个函数
计算西尔维斯特方程，CARE，DARE等代数方程
特殊矩阵运算
包含blcok_diag，circulant等将近30个函数
创建块对角矩阵，循环矩阵，相伴矩阵等等
其他
包含4个函数
BLAS，LSPACK等函数对象
Scipy库的线性代数模块包含将近100个各类函数，用于解决线性代数中的各类计算问题。

下面演示几种通过scipy.linalg来进行的常用计算。

2.
矩阵计算
提起线性代数，就不得不提矩阵运算。

2.1.特征值
矩阵的特征值和特征向量是矩阵理论中的重要概念，它们分别代表了矩阵对某些向量进行变换时所具有的特定的拉伸和旋转效果。

具体来说，对于一个给定的矩阵
A，如果存在一个非零的向量v，使得Av是v的一个固定的倍数，即Av=λv，那么λ就是A的一个特征值，v就是对应于特征值λ的特征向量。
特征值和特征向量在许多领域都有应用，包括图像处理、信号处理、数据压缩、物理学、经济学等。
它们在求解线性方程组、判定矩阵的稳定性、计算矩阵的秩等数学问题中也有重要的应用。"""

import numpy as np
import scipy.linalg as sla

A = np.random.rand(3, 3)
sla.eigvals(A)
# 运行结果（返回特征值）
# array([0.87067114 + 0.j, 0.25270355 + 0.j, 0.52811777 + 0.j])

sla.eig(A)

"""# 运行结果（返回特征值和特征向量）
(array([0.87067114 + 0.j, 0.25270355 + 0.j, 0.52811777 + 0.j]),
 array([[-0.55290631, -0.88616977, -0.80241551],
        [-0.73988407, 0.44869198, -0.51813093],
        [-0.38323122, 0.11566608, 0.29609067]]))
eigvals函数返回的是特征值，eig函数返回的是特征值和对应的特征向量。

2.2.奇异值
特征值和特征向量是针对方阵的，也就是NxN的矩阵。
实际场景中，很多矩阵并不是方阵，为了了解这类矩阵，就要对其进行奇异分解。

具体来说，对于一个m×n的矩阵A，奇异分解就是将其分解为三个矩阵的乘积：

一个m×r的矩阵U
一个r×r的对称正定矩阵S
以及一个r×n的矩阵V
其中r是由A的奇异值所决定的。A的奇异值就是S矩阵的对角线元素，也就是A的正特征值的非负平方根。
这些奇异值反映了矩阵A在一些方向上的拉伸或压缩效果。
"""
# 创建一个 4x3 的矩阵
A = np.random.rand(4, 3)

# 奇异分解，得到 U，S，V矩阵
U, S, V = sla.svd(A)
print("奇异值: {}".format(S))
"""# 运行结果
奇异值: [1.6804974  0.67865812 0.3322078]
2.3.逆矩阵
逆矩阵是指对于一个n阶方阵A，如果存在一个n阶方阵B，使得AB = BA = E，
则称方阵A是可逆的，并称方阵B是A的逆矩阵。
其中E是单位矩阵。

逆矩阵的重要意义在于它可以表示为某个线性变换的逆变换，从而在逆变换的研究和应用中起到关键作用。
此外，逆矩阵还与方程组的解、行列式的性质等领域紧密相关。
"""
A = np.random.rand(3, 3)

# 求解逆矩阵
sla.inv(A)

"""# 运行结果：
array([[-1.41573129, 0.13168502, 1.5952333],
       [3.572943, -1.02580488, 1.10932935],
       [-2.82777937, 2.10823192, -2.39404249]])
"""
# 非方阵
A = np.random.rand(4, 3)

# 非方阵求解逆矩阵会抛出异常
sla.inv(A)
"""# 运行结果：
ValueError: expected
square
matrix
Scipy库用inv函数求解逆矩阵非常简单，注意只有方阵能求解逆矩阵。

3.
线性方程组
其实求解线性方程组本质也是矩阵运算，比如下面的线性方程组：
3x+2y−z=1  −y+3z=−3  2x−2z=2
求解方式转换为系数矩阵和结果向量，然后求解：
"""
# 创建一个系数矩阵  
A = np.array([[3, 2, -1], [0, -1, 3], [2, 0, -2]])

# 创建一个结果向量  
b = np.array([1, -3, 2])

# 使用solve函数求解线性方程组  
ret = sla.solve(A, b)

# 输出解向量  
print("Solution vector ret:", ret)
"""# 运行结果：
Solution
vector
x: [0. - 0. - 1.]
4.
总结
本篇概要介绍了Scipy库的linalg模块，并演示了如何应用在求解矩阵和线性方程组。

linalg模块提供了非常丰富的各类函数，这里演示的几个函数目的是为了展示其使用方法，
线性代数中的各类运算几乎都可以在此模块中找到相应的函数。"""


